// clazy_help.cpp
//-------------------------------------------------------------------------------
//   (c) 2007 K.Danilov aka koder
//   distributed under GNU GPL v2.0 - see
//   http://www.gnu.org/licenses/gpl.html for full licens text
//   this file is part of plazyn python library
//
//   This program is free software; you can redistribute it and/or
//   modify it under the terms of the GNU General Public License
//   as published by the Free Software Foundation; (using version 2 of licence)
//    
//   This program is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU General Public License for more details.
//   
//   You should have received a copy of the GNU General Public License
//   along with this program; if not, write to the Free Software
//   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
//------------------------------------------------------------------------------
#include <Python.h>
#include <frameobject.h>
#include <code.h>
//------------------------------------------------------------------------------
extern "C" {
    PyObject * C_SetFrameObject_ByName(PyObject * fr,const char * name,PyObject * val){
        PyObject * obj = 0, * oname = 0;
        PyFrameObject * frame = (PyFrameObject *)fr;
        PyCodeObject * code = frame->f_code;
		int s1 = code->co_nlocals;
		int s2 = PyTuple_GET_SIZE(code->co_freevars);
		for(int i = 0; i != s1 + s2; ++i){
			if ( i < s1 )
				oname = PyTuple_GET_ITEM(code->co_varnames,i);
			else
				oname = PyTuple_GET_ITEM(code->co_freevars,i);
			if ( 0 == strcmp(PyString_AS_STRING(oname),name)){
				if ( i < s1 ){
					//if normal local variable
					Py_INCREF(val);
					oname = frame->f_localsplus[i];
					frame->f_localsplus[i] = val;
				}else{
					//if closure variable
					oname = PyCell_Get(frame->f_localsplus[i]);
					if ( 0 != PyCell_Set(frame->f_localsplus[i],val)){
						PyErr_SetString(PyExc_RuntimeError, "Internal error with cell var");
						return (PyObject *)NULL;
					}
				}
				return oname;
			}
		}
	    PyErr_Format(PyExc_NameError, "Variable %s not found",name);
        return (PyObject *)NULL;
    }
    // This function don't work. If you understand why feel free to fix ;)
    PyObject * C_SetFrameObject_ByVal(PyObject * fr,PyObject * orig,PyObject * val){
        PyErr_SetString(PyExc_RuntimeError, "Don't use this function yet - it has unresolved bug");
        return 0;
        PyFrameObject * frame = (PyFrameObject *)fr;
		PyObject * res = 0;
        PyCodeObject * code = frame->f_code;
		int sz = PySequence_Size(code->co_varnames) + PySequence_Size(code->co_freevars);
		for(int i = 0; i != PySequence_Size(code->co_varnames); ++i){
			if ( frame->f_localsplus[i] == orig ){
				//if closure variable
				if ( i >= code->co_nlocals ){
					res = PyCell_Get(frame->f_localsplus[i]);
					if ( 0 != PyCell_Set(frame->f_localsplus[i],val)){
						PyErr_SetString(PyExc_RuntimeError, "Internal error with cell var");
						return (PyObject *)NULL;
					}
					return res;
				}else{
					Py_INCREF(val);
					res = frame->f_localsplus[i];
					frame->f_localsplus[i] = val;
					return res;
				}
			}
		}
	    PyErr_SetString(PyExc_RuntimeError, "Given variable not found");
        return (PyObject *)NULL;
    }
};
//-------------------------------------------------------------------------------
